package com.buka.recipe.system.service.impl;

import com.buka.recipe.system.entity.Department;
import com.buka.recipe.system.entity.User;
import com.buka.recipe.system.repository.DepartmentRepository;
import com.buka.recipe.system.repository.UserRepository;
import com.buka.recipe.system.service.DepartmentService;
import com.buka.recipe.system.utils.UserUtils;
import jakarta.persistence.criteria.Predicate;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

@Service
public class DepartmentServiceImpl implements DepartmentService {

    private final DepartmentRepository departmentRepository;
    private final UserRepository userRepository;

    @Autowired
    public DepartmentServiceImpl(DepartmentRepository departmentRepository, UserRepository userRepository) {
        this.departmentRepository = departmentRepository;
        this.userRepository = userRepository;
    }


    @Override
    public void save(Department department) {
        departmentRepository.save(department);
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    public void delete(Department department, Boolean confirm) {
        List<Department> departments = departmentRepository.findDepartmentsByLevelLike(department.getLevel() + "%");
        List<User> accounts = userRepository.findUsersByDepartmentId(department.getId());
        if (confirm) {
            if (departments == null) {
                departments = new ArrayList<>();
            }
            if (accounts != null) {
                userRepository.deleteAll(accounts);
            }
            departments.add(department);
            departmentRepository.deleteAll(departments);
        } else {
            if (departments != null && !departments.isEmpty()) {
                throw new RuntimeException("包含子部门，请确认是否删除");
            }
            if (accounts != null && !accounts.isEmpty()) {
                throw new RuntimeException("包含账号，请确认是否删除");
            }
            departmentRepository.delete(department);
        }
    }

    @Override
    public Department getDepartmentById(Integer id) {
        Department userDepartment = UserUtils.getDepartment();
        if (userDepartment.getId().equals(id)) {
            return userDepartment;
        }
        String level = userDepartment.getLevel();
        Specification<Department> specification = ((root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("id"), id));
            list.add(criteriaBuilder.like(root.get("level"), level + "%"));
            Predicate[] predicates = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(predicates));
        });
        return departmentRepository.findOne(specification).orElse(null);
    }

    @Override
    public List<Department> getDepartmentsByIds(List<Integer> ids) {
        return getAll().stream().filter(item -> ids.contains(item.getId())).toList();
    }

    @Override
    public Department getDepartmentByNameAndParentId(String name, int parentId) {
        return departmentRepository.findDepartmentByNameAndParentId(name, parentId);
    }

    @Override
    public List<Department> getSubDepartmentsById(Integer id) {
        Department department = departmentRepository.findById(id).orElse(null);
        if (department == null) {
            return List.of();
        }
        return departmentRepository.findDepartmentsByLevelLike(department.getLevel() + "%");
    }

    @Override
    public Page<Department> getAll(Integer parentId, String name, Integer current, Integer pageSize) {
        String level = UserUtils.getDepartmentLevel();
        if (pageSize < 1) {
            pageSize = 10;
        }
        Pageable pageable = PageRequest.of(current, pageSize);
        Specification<Department> specification = ((root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (StringUtils.hasLength(name)) {
                list.add(criteriaBuilder.like(root.get("name"), "%" + name + "%"));
            }
            if (parentId != null) {
                Predicate typePredicate = criteriaBuilder.equal(root.get("parentId"), parentId);
                list.add(typePredicate);
            }
            if (StringUtils.hasLength(level)) {
                list.add(criteriaBuilder.like(root.get("level"), level + "%"));
            }
            Predicate[] predicates = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(predicates));
        });
        return departmentRepository.findAll(specification, pageable);
    }

    @Override
    public List<Department> getAll() {
        String level = UserUtils.getDepartmentLevel();
        return departmentRepository.findDepartmentsByLevelLike(level + "%");
    }

    @Override
    public void updateAll(List<Department> departments) {
        departmentRepository.saveAll(departments);
    }

    @Override
    public boolean checkDepartmentAuth(Integer id) {
        Department userDepartment = UserUtils.getDepartment();
        if (userDepartment.getId().equals(id)) {
            return true;
        }
        String level = userDepartment.getLevel();
        Department department = departmentRepository.findDepartmentByLevelLikeAndId(level + "%", id);
        return department != null;
    }

}
